/**
 * 
 */
package com.onewingu.gcs.server;

import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

import javax.jdo.PersistenceManager;
import javax.jdo.Query;

import com.onewingu.gcs.client.GContactSyncService;
import com.onewingu.gcs.shared.GroupInfo;
import com.google.appengine.api.users.User;
import com.google.appengine.api.users.UserService;
import com.google.appengine.api.users.UserServiceFactory;
import com.google.gdata.data.contacts.ContactGroupEntry;
import com.google.gdata.data.contacts.ContactGroupFeed;
import com.google.gwt.user.server.rpc.RemoteServiceServlet;

/**
 * @author er66
 *
 */
@SuppressWarnings("serial")
public class GContactSyncServiceImpl extends RemoteServiceServlet implements
		GContactSyncService {

	public String getSourceAccount() throws Exception {
		PersistenceManager pm = PMF.get().getPersistenceManager();
		Query query = pm.newQuery(SourceAccount.class);
		List<SourceAccount> results = (List<SourceAccount>)query.execute();
		if(results.size() == 0) {
			return null;
		}
		SourceAccount sa = results.get(0);
		pm.close();
				
		return sa.getUsername();
	}
	
	public void setSourceAccount(String username, String password) throws Exception {
		SourceAccount sa = null;
		
		UserService userService = UserServiceFactory.getUserService();
		User user = userService.getCurrentUser();
		String id = user.getUserId();
		
		String encPassword = Encrypter.encrypt(password);
		
		PersistenceManager pm = PMF.get().getPersistenceManager();
		try {
			Query query = pm.newQuery(SourceAccount.class);
			List<SourceAccount> results = (List<SourceAccount>)query.execute();
			if(results.size() == 0) {
				sa = new SourceAccount(id, username, encPassword);
			} else {
				sa = results.get(0);
				sa.setId(id);
				sa.setUsername(username);
				sa.setEncryptedPassword(encPassword);
			}

			pm.makePersistent(sa);
		} finally {
			pm.close();
		}
	}

	public List<GroupInfo> getGroups(String username) throws Exception {
		PersistenceManager pm = PMF.get().getPersistenceManager();
		Query query = pm.newQuery(SharedGroup.class);
		List<SharedGroup> results = (List<SharedGroup>)query.execute();

		List<GroupInfo> groupInfos = new ArrayList<GroupInfo>();
		
		try {
			Sync2 s2 = new Sync2(pm);
			ContactGroupFeed groupFeed = s2.getGroupFeed(username.substring(0, username.indexOf('@')));

			if(groupFeed == null)
				throw new Exception("groupFeed is null");

			if(results == null)
				throw new Exception("results is null");

			for(ContactGroupEntry group : groupFeed.getEntries()) {
				if(group == null)
					throw new Exception("group is null");

				if(group.hasSystemGroup())
					continue;

				GroupInfo groupInfo = new GroupInfo(group.getId(), group.getTitle().getPlainText());
				groupInfos.add(groupInfo);

				for(SharedGroup sharedGroup : results) {
					if(sharedGroup.getSaGroupId().equalsIgnoreCase(group.getId())) {
						groupInfo.setShared(true);
						break;
					}
				}
			}
		} finally {
			pm.close();
		}
		
		return groupInfos;
	}

	public void setSharedGroups(String saUsername, List<GroupInfo> groups) throws Exception {
		PersistenceManager pm = PMF.get().getPersistenceManager();
		try {
			System.out.println("setSharedGroups");
			
			Query query = pm.newQuery(SharedGroup.class);
			List<SharedGroup> results2 = (List<SharedGroup>)query.execute();
			List<SharedGroup> results = new ArrayList<SharedGroup>(results2);
			
			Map<String, SharedGroup> sharedGroupMap = new HashMap<String, SharedGroup>();
			for(SharedGroup sharedGroup : results) {
				sharedGroupMap.put(sharedGroup.getSaGroupId(), sharedGroup);
			}
			
			Map<String, GroupInfo> groupInfoMap = new HashMap<String, GroupInfo>();
			for(GroupInfo groupInfo : groups) {
				groupInfoMap.put(groupInfo.getGroupId(), groupInfo);
			}
			
			List<SharedGroup> sharedGroupsToDelete = new ArrayList<SharedGroup>();
			for(SharedGroup sharedGroup : results) {
				if(!(groupInfoMap.containsKey(sharedGroup.getSaGroupId()))) {
					sharedGroupsToDelete.add(sharedGroup);
				}
			}
			results.removeAll(sharedGroupsToDelete);
			pm.deletePersistentAll(sharedGroupsToDelete);
			
			for(GroupInfo groupInfo : groups) {
				SharedGroup sharedGroup = sharedGroupMap.get(groupInfo.getGroupId());
				if(sharedGroup != null)
					continue;
				sharedGroup = new SharedGroup(groupInfo.getGroupId());
				results.add(sharedGroup);
			}
			
			pm.makePersistentAll(results);
		} finally {
			pm.close();
		}
		
		pm = PMF.get().getPersistenceManager();
		try {
			new Sync2(pm).sync();
		} finally {
			pm.close();
		}
	}
}
